<?php

/**
 * @tutorial 
 +----------------------------------------------------------------
 * $this->retriveByUsername('foo');
 * 
 * SELECT * FROM $this->_table WHERE username = 'foo';
 +----------------------------------------------------------------
 * @throws PDOException
 * @author littlexiang
 * @version $Id: Model.php 685 2009-08-03 06:28:25Z songxiang $
 */

abstract class Model {
    
    protected $_table;
    /**
     * @var PDO
     */
    protected $_connection;
    protected $_connectionName = 'default';
    
    public function __construct ($connName = '') {
        if (empty($this->_connection)) {
            $conf = Config::get('db');
            $this->_connection = new PDO($conf['dsn'], $conf['username'], $conf['password'], array(
                PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
            $this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
    }
    
    /**
     *
     * @param array $value
     * @return int last_insert_id
     * @example 
     +--------------------------------------------------------------------
     * $this->insert(array(
     * 			'username' => 'foo', 
     * 			'email' => 'foo@bar.com'));
     * 
     * INSERT INTO e3d_user SET username = 'foo', email = 'foo@bar.com'
     +--------------------------------------------------------------------
     */
    public function insert (array $value) {
        $query = 'INSERT INTO ' . $this->_table . ' SET';
        foreach ($value as $k => $v) {
            $query .= ' ' . $k . ' = :' . $k . ',';
        }
        $query = rtrim($query, ',');
        return $this->execute($query, $value);
    }
    
    /**
     *
     * @param array $value
     * @param string $where
     * @param array $param
     * @return number of rows affected
     * @example 
     +--------------------------------------------------------------------
     * $this->update(array(
     * 			'username' => 'foo', 
     * 			'email' => 'foo@bar.com'), 'userid = :userid ', array('userid' => 1));
     * 
     * UPDATE e3d_user SET username = 'foo', email = 'foo@bar.com' WHERE userid = 1
     +--------------------------------------------------------------------
     */
    public function update (array $value, $where, $param = array()) {
        $query = 'UPDATE ' . $this->_table . ' SET';
        foreach ($value as $k => $v) {
            $query .= ' ' . $k . ' = :' . $k . ',';
        }
        $query = rtrim($query, ',');
        $query .= ' WHERE ' . $where;
        return $this->execute($query, array_merge($value, $param));
    }
    
    /**
     * 获取此表单条记录
     *
     * @param string $where
     * @param array $params
     * @return Model_PureObject
     */
    public function retrive ($where = '', array $param = array()) {
        $query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . ($where ? $where : '1') . ' LIMIT 1';
        return $this->fetch($query, $param);
    }
    
    /**
     * 获取此表记录集合
     *
     * @param string $where
     * @param array $params
     * @return array of Model_PureObjects
     */
    public function retriveAll ($where = '', array $param = array()) {
        $query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . ($where ? $where : '1');
        return $this->fetchAll($query, $param);
    }
    
    /**
     * 获取单条记录
     *
     * @param string $query raw sql
     * @param array $params
     * @return Model_PureObject
     */
    public function fetch ($query, array $params = array()) {
        $stmt = $this->getPDO()->prepare($query);
        $stmt->execute($params);
        return $ret = $stmt->fetchObject('Model_PureObject');
    }
    
    /**
     * 获取记录集合
     *
     * @param string $query raw sql
     * @param array $params
     * @return array of Model_PureObjects
     */
    public function fetchAll ($query, array $params = array()) {
        $stmt = $this->getPDO()->prepare($query);
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_CLASS, 'Model_PureObject');
    }
    
    /**
     * for updata/insert/delete
     * @param string $query raw sql
     * @return int number of rows affected
     */
    public function execute ($query, array $param = array()) {
        $stmt = $this->getPDO()->prepare($query);
        $stmt->execute($param);
        return $stmt->rowCount();
    }
    
    /**
     * 获取当前连接
     *
     * @return PDO
     */
    public function getPDO () {
        return $this->_connection;
    }
    
    /**
     * $this->userTable returns table_prefix . 'user'
     *
     * @param string $name
     * @return string
     */
    public function __get ($name) {
        $search = array(
            'A' , 
            'B' , 
            'C' , 
            'D' , 
            'E' , 
            'F' , 
            'G' , 
            'H' , 
            'I' , 
            'J' , 
            'K' , 
            'L' , 
            'M' , 
            'N' , 
            'O' , 
            'P' , 
            'Q' , 
            'R' , 
            'S' , 
            'T' , 
            'U' , 
            'V' , 
            'W' , 
            'X' , 
            'Y' , 
            'Z');
        $replace = array(
            '_a' , 
            '_b' , 
            '_c' , 
            '_d' , 
            '_e' , 
            '_f' , 
            '_g' , 
            '_h' , 
            '_i' , 
            '_j' , 
            '_k' , 
            '_l' , 
            '_m' , 
            '_n' , 
            '_o' , 
            '_p' , 
            '_q' , 
            '_r' , 
            '_s' , 
            '_t' , 
            '_u' , 
            '_v' , 
            '_w' , 
            '_x' , 
            '_y' , 
            '_z');
        $match = array();
        if (preg_match('~([a-zA-Z]+)Table~', $name, $match)) {
            return Config::get('db', 'table_prefix') . str_replace($search, $replace, $match[1]);
        } else {
            return $this->$name;
        }
    }

}
?>